package com.gsd.leetcode.controller;


import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

@RestController
@RequestMapping("swagger" )
@Api(tags = {"MyController","Swagger学习控制器"})
public class MyArrayList {

    // 1.删除排序数组中的重复项
    @PostMapping("/removeDuplicates")
    public int removeDuplicates(int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int i = 1, j = 1;
        while (i < n) {
            if (nums[i] != nums[i - 1]) {
                nums[j] = nums[i];
                ++j;
            }
            ++i;
        }
        return j;
    }


    //2.买卖股票的最佳时机 II
    //给定一个数组 prices ，其中 prices[i] 是一支给定股票第 i 天的价格。
    //设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易（多次买卖一支股票）。
    //注意：你不能同时参与多笔交易（你必须在再次购买前出售掉之前的股票）。
    @PostMapping("/maxProfit")
    public int maxProfit(int[] prices) {
        int max=0;
        for(int i =1;i<prices.length;i++){
            if(prices[i]>prices[i-1]){
                max = max +(prices[i]-prices[i-1]);
            }
        }
        return max;
    }

    //3.旋转数组
    //给定一个数组，将数组中的元素向右移动 k 个位置，其中 k 是非负数。
    @PostMapping("/rotate")
    public void rotate(int[] nums, int k) {
        k = k % nums.length;
        //定义长度为k的tmp数组
        int temp[] = new int[k];
        int j = 0;
        //将数组中最后k个元素存入tmp中
        for (int i = nums.length - k; i < nums.length; i++) {
            temp[j++] = nums[i];
        }
        //将数组中的元素向后移动k个元素
        for (int i = nums.length - k - 1; i >= 0; i--) {
            nums[i+k] = nums[i];
        }
        //将临时tmp数组存入元数组中
        for (int i = 0; i < temp.length; i++) {
            nums[i] = temp[i];
        }
    }


    //4.两数之和
    //给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出 和为目标值 的那 两个 整数，并返回它们的数组下标。
    //你可以假设每种输入只会对应一个答案。但是，数组中同一个元素在答案里不能重复出现。
    @PostMapping("/twoSum")
    public int[] twoSum(int[] nums, int target) {
        for(int i =0;i<nums.length;i++){
            for(int j =i+1;j<nums.length;j++){
                if(target==nums[i]+nums[j]){
                    return new int[] {i,j};
                }
            }
        }
        return new int []{0,0};
    }

    //5 存在重复元素
    //给定一个整数数组，判断是否存在重复元素。
    //如果存在一值在数组中出现至少两次，函数返回 true 。如果数组中每个元素都不相同，则返回 false 。
    //法1  进行数组排序，遍历数组相邻两个相同
    public boolean containsDuplicate1(int[] nums) {
        Arrays.sort(nums);
        for(int i=0;i<nums.length-1;i++){
            if(nums[i]==nums[i+1]){
                return true;
            }
        }
        return false;
    }
    //法二  使用set集合进行检测，set不能重复
    public boolean containsDuplicate2(int[] nums) {
        HashSet<Integer> hashSet = new HashSet<>();
        for (int num : nums){
            if (hashSet.add(num)==false){
                return true;
            }
        }

        return false;
    }

    //6只出现一次的数字
    //给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。
    //法1 使用位运算解决，a^a=0；自己和自己异或等于0//a^0=a；任何数字和0异或还等于他自己//a^b^c=a^c^b；异或运算具有交换律
    public int singleNumber(int[] nums) {
        int res = 0;
        for (int num : nums) {
            res = res ^ num;
        }
        return res;

    }
    //法二 使用set方法，相同将元素移除，最后只剩一个
    public int singleNumber1(int[] nums) {
        Set<Integer> set=new HashSet();
        for(Integer num : nums){
            if(set.add(num)==false){
                set.remove(num);
            }
        }
        return (int) set.toArray()[0];
    }

    //7、给定一个由 整数 组成的 非空 数组所表示的非负整数，在该数的基础上加一。
    public int[] plusOne(int[] digits) {
        int length = digits.length;
        for (int i = length - 1; i >= 0; i--) {
            if (digits[i] != 9) {
                //如果数组当前元素不等于9，直接加1
                //然后直接返回
                digits[i]++;
                return digits;
            } else {
                //如果数组当前元素等于9，那么加1之后
                //肯定会变为0，我们先让他变为0
                digits[i] = 0;
            }
        }
        //除非数组中的元素都是9，否则不会走到这一步，
        //如果数组的元素都是9，我们只需要把数组的长度
        //增加1，并且把数组的第一个元素置为1即可
        int temp[] = new int[length + 1];
        temp[0] = 1;
        return temp;

    }



    //9、两个数组的交集 给定两个数组，编写一个函数来计算它们的交集。
    // 如果数组中的所有元素都是9，类似9999，加1之后肯定会变为10000，也就是数组长度会增加1位。
    //如果数组的元素只要有一个不是9，加1之后直接返回即可。
    public int[] intersect(int[] nums1, int[] nums2) {
        // 先对两个数组进行排序
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i = 0;
        int j = 0;
        List<Integer> list = new ArrayList<>();
        while (i < nums1.length && j < nums2.length) {
            if (nums1[i] < nums2[j]) {
                // 如果i指向的值小于j指向的值，，说明i指向
                // 的值小了，i往后移一步
                i++;
            } else if (nums1[i] > nums2[j]) {
                // 如果i指向的值大于j指向的值，说明j指向的值
                // 小了，j往后移一步
                j++;
            } else {
                // 如果i和j指向的值相同，说明这两个值是重复的，
                // 把他加入到集合list中，然后i和j同时都往后移一步
                list.add(nums1[i]);
                i++;
                j++;
            }
        }
        //把list转化为数组
        int index = 0;
        int[] res = new int[list.size()];
        for (int k = 0; k < list.size(); k++) {
            res[index++] = list.get(k);
        }
        return res;
    }


}

